import {TyFeatureLayer} from '@/plugin/map/tyMapUtlis'
import {createEmpty, extendCoordinate} from 'ol/extent'
import {mapGetters} from 'vuex'
import {Select} from 'ol/interaction'
import {Feature} from 'ol'
import {Point} from 'ol/geom'
import {Style, Icon, Stroke, Fill, Text, Circle} from 'ol/style'
import {Vector as LayerVec} from 'ol/layer'
import {Vector as SourceVec, Cluster} from 'ol/source'

export const MarkerMixin = {
  props: {
    markerPoints: {
      type: Array,
      default: () => {
        return []
      }
    },
    markerProps: {
      type: Object,
      default: () => {
        return {
          id: 'id',
          title: 'title',
          icon: 'icon',
          target: 'target'
        }
      }
    },
    isFit: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    markerPoints: {
      handler() {
        this.showMarkerFeature()
      }
    }
  },
  data() {
    return {
      // marker标记数组
      markers: [],

      //
      markerFeatures: [],
      // 当前显示的兴趣点标记
      marker: null,
      // 上一次点击的兴趣点标记
      lastMarker: null,

      // 图层集合
      markerFeature: {
        default: undefined
      },
      // 最后一次点击的Feature
      lastFeature: {
        default: undefined
      },
      // 最后一次点击的Feature的层级
      lastFeatureZIndex: {
        default: undefined
      }
    }
  },
  computed: {
    ...mapGetters('topevery', {
      fileUrl: 'systemConfig/fileUrl'
    }),
    getMapLayerIcon() {
      return (type) => {
        const uri = this.$store.getters['topevery/mapLayerIcon/mapLayerIcon'](type)
        return `${this.fileUrl}${uri}`
      }
    },
    getIconTitle() {
      return this.markerProps.title
    },
    getFeatureIcon() {
      return this.markerProps.icon
    },
    getFeatureId() {
      return this.markerProps.id
    },
    getFeatureTarget() {
      return this.markerProps.target
    }
  },
  methods: {
    /**
     * @Description 显示Feature坐标点
     * @Date 2019/12/3 17:24
     * @Author yuesheng.zhu@topevery.club
     */
    showMarkerFeature(markers = this.markerPoints, isFit = this.isFit, key = 'default') {
      this.clearMarkerFeature(key)
      markers.map((item, index) => {
        this.initMarkerFeature(item, index, key)
      })
      if (markers.length > 0 && isFit) {
        this.map.fitByFeatures(this.markerFeature[key].getFeatures())
        if (markers.length > 1) {
          this.map.zoomOut(0.5)
        }
      }
      return this.markerFeature[key] === undefined ? undefined : this.markerFeature[key].getFeatures()
    },

    /**
     * @Description 初始化Feature坐标图层
     * @Date 2019/12/3 17:24
     * @Author yuesheng.zhu@topevery.club
     */
    initMarkerFeature(item, index, key = 'default') {
      if (this.markerFeature[key] === undefined) {
        this.markerFeature[key] = new TyFeatureLayer(this.option)
        this.initFeatureSelect(key)
      }
      this.markerFeature[key].addPoint(item.coordinates, this.initMakerFeatureStyle(item, index), item[this.getFeatureId],
        {
          ...item, ...item.data, ...{
            target: item[this.getFeatureTarget],
            type: 'marker'
          }, ...this.setFeatureItem(item)
        }, false)
    },

    /**
     * @Description 初始化Feature选择方法
     * @Date 2019/12/3 17:24
     * @Author yuesheng.zhu@topevery.club
     */
    initFeatureSelect(key = 'default') {
      const selectSingleClick = new Select({
        style: false,
        layers: [this.markerFeature[key].getVectorLayer()]
      })
      selectSingleClick.on('select', (event) => {
        console.log('event==>', event)
        const features = event.target.getFeatures().getArray()
        if (features.length > 0) {
          const data = features[0].getProperties()
          if (key === 'car' || key === 'user' || key === 'boat' || key === 'fisher' || key === 'appAlarm' || key === 'alarm' || key === 'deploy' || key === 'judgeAlarm' || key === 'help' || key === 'tourist' || key === 'app') {
            this.$emit('map-click', data)
          } else {
            if (data.type === 'marker' && data.callback) {
              data.callback(data, features[0], event)
            }
          }
        }
      })
      this.map.getMap().removeInteraction(selectSingleClick)
      this.map.getMap().addInteraction(selectSingleClick)
    },

    /**
     * @Description 设置Feature详细信息
     * @Date 2019/12/3 17:24
     * @Author yuesheng.zhu@topevery.club
     */
    setFeatureItem(item) {
      return {
        animate: item.animate !== undefined ? item.animate : true,
        centerOffset: item.centerOffset,
        callback: (data, feature) => {
          this.handleFeatureSelect(data, feature, item.clickType)
        }
      }
    },

    /**
     * @Description 点击item信息并调用点击Feature方法
     * @Date 2019/12/3 17:24
     * @Author yuesheng.zhu@topevery.club
     */
    handleItemSelect(item, type = undefined, key = 'default', back = true) {
      this.handleFeatureSelect(item, this.markerFeature[key].getFeatureById(item[this.getFeatureId]), type, key, back)
    },

    /**
     * @Description 点击Feature并调用回调方法
     * @Date 2019/12/3 17:24
     * @Author yuesheng.zhu@topevery.club
     */
    handleFeatureSelect(item, feature, type = undefined, key = 'default', back = true) {
      let style = null
      if (this.lastFeature[key]) {
        const properties = this.lastFeature[key].getProperties()
        delete properties['iconUrl']
        style = this.initMakerFeatureStyle(properties, this.lastFeatureZIndex[key], 0)
        this.lastFeature[key].setStyle(style)
      }
      this.lastFeature[key] = feature
      this.lastFeatureZIndex[key] = feature.getStyle()[0].getZIndex()
      if (item[this.getFeatureIcon] && item[this.getFeatureTarget]) {
        item.iconUrl = '/image/map/loc-blue.png'
      }
      style = this.initMakerFeatureStyle(item, this.lastFeatureZIndex[key] + 1000, 0, true)
      feature.setStyle(style)
      if (item.animate) {
        this.map.getMap().getView().animate({
          center: item.coordinates,
          duration: 500
        })
      }
      if (back) {
        if (type === 'poi') {
          this.handlePoiClick(item)
        } else {
          this.$emit('marker-click', item)
        }
      }
    },

    /**
     * @Description 设置Feature坐标点图层样式
     * @Date 2019/12/3 17:24
     * @Author yuesheng.zhu@topevery.club
     */
    initMakerFeatureStyle(item, index = 1, addIndex = 4000, isClick = false) {
      const styles = []
      const icon = item.iconUrl || (item[this.getFeatureIcon] || this.initMarkerFeatureIcon(item[this.getFeatureTarget]))
      const imgScale = item.imgScale || 0.9
      const title = item[this.getIconTitle]
      if (title) {
        const len = item.len || 16
        const anchor = item.anchor || {x: 0.4, y: 1.8}
        const offsetX = item.offsetX || 0.4
        const textBgColor = !isClick ? (item.textBgColor || '#fff') : '#FFFAC5'

        const canvas = document.createElement('canvas')
        const context = canvas.getContext('2d')
        // eslint-disable-next-line no-control-regex
        const length = title.replace(/[^\x00-\xff]/g, '**').length
        canvas.width = length * len
        canvas.height = 35
        const x = 0
        const y = 0
        const w = canvas.width
        const h = canvas.height
        const r = 15
        // 缩放
        context.scale(0.8, 0.8)
        context.fillStyle = textBgColor
        context.beginPath()
        context.moveTo(x + r, y)
        context.arcTo(x + w, y, x + w, y + h, r)
        context.arcTo(x + w, y + h, x, y + h, r)
        context.arcTo(x, y + h, x, y, r)
        context.arcTo(x, y, x + w, y, r)
        // 设置阴影
        context.shadowColor = 'rgba(0, 0, 0, 0.2)' // 颜色
        context.shadowBlur = 5 // 模糊尺寸
        context.shadowOffsetX = 2 // 阴影Y轴偏移
        context.shadowOffsetY = 1 // 阴影X轴偏移
        context.closePath()
        context.fill()
        styles.push(
          new Style({
            image: new Icon({
              img: canvas,
              imgSize: [w, h],
              anchor: [anchor.x, anchor.y]
            }),
            text: new Text({
              font: '16px Microsoft YaHei',
              text: title,
              offsetX: length * offsetX,
              offsetY: -46,
              fill: new Fill({
                color: '#06c'
              })
            }),
            zIndex: !isClick ? (index + addIndex) : index
          })
        )
      }
      styles.push(
        new Style({
          image: new Icon({
            src: icon,
            scale: imgScale,
            anchor: [0.5, 0.9]
          }),
          zIndex: !isClick ? (index + addIndex) : index
        })
      )
      return styles
    },

    /**
     * @Description 初始化Feature图标
     * @Date 2019/12/3 17:25
     * @Author yuesheng.zhu@topevery.club
     */
    initMarkerFeatureIcon(target) {
      switch (target) {
        case 'case':
          return this.getMapLayerIcon('normal_case_icon')
        case 'on_time_case':
          return this.getMapLayerIcon('onTimeOut_case_icon')
        case 'time_case':
          return this.getMapLayerIcon('timeOut_case_icon')
        case 'staff':
          return this.getMapLayerIcon('supervisor_icon')
        case 'car':
          return this.getMapLayerIcon('car_icon')
        case 'video':
          return this.getMapLayerIcon('video_icon')
        default:
          return './image/map/loc-red.png'
      }
    },

    /**
     * @Description 清除marker标记
     * @Date 2019/12/4 13:33
     * @Author yuesheng.zhu@topevery.club
     */
    clearMarkerFeature(key = 'default') {
      if (this.markerFeature[key] !== undefined) {
        this.markerFeature[key].clear()
      }
      // this.map.getMap().removeLayer(this.markerFeature[key])
    },
    clearMarkerFeatureNew(key = 'default') {
      this.map.getMap().removeLayer(this.markerFeature[key])
    },
    /**
     * @Description 清除所有marker标记
     * @Date 2019/12/4 13:33
     * @Author yuesheng.zhu@topevery.club
     */
    clearAllMarkerFeature() {
      for (let make in this.markerFeature) {
        this.clearMarkerFeature(make)
      }
      this.$emit('marker-clearTrajectory')
    },
    /**
     * @Description 显示marker标记
     * @Date 2019/5/28 10:39
     * @Author yuesheng.zhu@topevery.club
     */
    showMarker(markers = this.markerPoints) {
      this.clearMarker()
      const extent = createEmpty()
      markers.map((item) => {
        extendCoordinate(extent, item.coordinates)
        item.marker = this.createMarker(item)
        this.markers.push(item.marker)
      })
      if (markers.length > 0) {
        this.map.getMap().getView().fit(extent, this.map.getMap().getSize())
      }
    },

    /**
     * @Author yuesheng.zhu@topevery.club
     * @Date 2019/5/28 10:39
     * @Description 清除marker标记
     */
    clearMarker() {
      this.markers.map((marker) => {
        marker.dispose()
      })
      this.markers = []
      if (this.marker !== null) {
        this.marker.dispose()
      }
      if (this.lastMarker !== null) {
        this.lastMarker.dispose()
      }
    },
    /**
     * @Description 创建marker标记
     * @Date 2019/5/16 15:38
     * @Author yuesheng.zhu@topevery.club
     */
    createMarker(item, iconUrl) {
      return this.map.setPointMarker({
        markerId: item.id,
        coordinate: item.coordinates,
        morePoint: true,
        animate: item.animate !== undefined ? item.animate : false,
        icon: iconUrl || (item.icon || (item[this.getFeatureIcon] || this.initMarkerFeatureIcon(item[this.getFeatureTarget]))),
        title: item[this.getIconTitle] || null,
        centerOffset: item.centerOffset,
        stopEvent: item.stopEvent || false,
        data: item,
        callback: (marker, data) => {
          this.handleMarkerClick(data, item.clickType || undefined)
        }
      })
    },
    /**
     * @Author yuesheng.zhu@topevery.club
     * @Date 2019/5/16 15:38
     * @Description 点击marker标记移动地图
     */
    handleMarkerClick(item, type = undefined) {
      if (this.lastMarker !== null) {
        this.lastMarker.show()
      }
      this.lastMarker = item.marker
      this.lastMarker.hide()
      if (this.marker !== null) {
        this.marker.dispose()
      }
      let iconUrl = null
      if (this.validatenull(item[this.getFeatureIcon]) && this.validatenull(item[this.getFeatureTarget])) {
        iconUrl = '/image/map/loc-blue.png'
      }
      this.marker = this.createMarker(item, iconUrl)
      this.marker.setIndex(6000)
      this.map.getMap().getView().animate({
        center: item.coordinates,
        duration: 500
      })
      this.$emit('marker-click', item)
    },
    massiveFeature(markers = this.markerPoints, isFit = this.isFit, key = 'default') {
      if (this.markerFeature[key] === undefined) {
        this.markerFeature[key] = new TyFeatureLayer(this.option)
      }
      // 创建Feature对象集合
      let features = new Array()
      markers.map((item, index) => {
        features.push(new Feature({
          geometry: new Point(item.coordinates),
          data: item
        }))
      })
      // 矢量要素数据源
      let source = new SourceVec({
        features: features
      })
      // 聚合标注数据源
      let clusterSource = new Cluster({
        distance: 40,
        source: source
      })
      // 加载聚合标注的矢量图层
      let styleCache = {}                    //用于保存特定数量的聚合群的要素样式
      let that = this
      this.markerFeature[key] = new LayerVec({
        source: clusterSource,
        style: function (feature, resolution) {
          let size = feature.get('features').length          //获取该要素所在聚合群的要素数量
          let style = styleCache[size]
          let data = {}
          if (size >= 2) {
            if (!style) {
              style = [
                new Style({
                  image: new Circle({
                    radius: 10,
                    stroke: new Stroke({
                      color: '#fff'
                    }),
                    fill: new Fill({
                      color: '#3399CC'
                    })
                  }),
                  text: new Text({
                    text: size.toString(),
                    fill: new Fill({
                      color: '#fff'
                    })
                  })
                })
              ]
              styleCache[size] = style
            }
          } else {
            data = feature.get('features')[0].values_.data
            style = styleCache[data.target + data.id]
            if (!style) {
              style = that.initMakerFeatureStyle(data, 1000, 0, true)
              styleCache[data.target + data.id] = style
            }
          }
          return style
        }
      })
      //
      this.map.getMap().addLayer(this.markerFeature[key])
      this.intMassiveFeatureClick(this.markerFeature[key], key)
    },
    intMassiveFeatureClick(layers, key = 'default') {
      const selectSingleClick = new Select({
        style: false,
        layers: [layers]
      })
      selectSingleClick.on('select', (event) => {
        // console.log('event==>',event)
        const features = event.target.getFeatures().getArray()
        // console.log('features==>',features)
        if (features.length > 0) {
          const data = features[0].get('features')[0].values_.data
          // console.log('data==>',data)
          if (key === 'car' || key === 'user' || key === 'boat' || key === 'fisher' || key === 'appAlarm' || key === 'alarm' || key === 'deploy' || key === 'judgeAlarm' || key === 'help' || key === 'tourist') {
            this.$emit('map-click', data)
          } else {
            if (data.type === 'marker' && data.callback) {
              data.callback(data, features[0], event)
            }
          }
        }
      })
      this.map.getMap().removeInteraction(selectSingleClick)
      this.map.getMap().addInteraction(selectSingleClick)
    }
  }
}
